package cn.iocoder.yudao.adminserver.franky.LRU;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description:
 * @Author: franky
 * @CreateDate: 2021/4/14 3:42 下午
 * @Version: 1.0
 */
public class LRUNode {

    Integer capacity;
    Map<String, Node> lruMap;
    Node head;
    Node tail;


    public LRUNode(Integer capacity) {
        this.capacity = capacity;
        lruMap = new ConcurrentHashMap<>();

    }

    public Node get(String key) {
        if (!lruMap.containsKey(key))
            return null;
        Node node = lruMap.get(key);
        refreshNode(node);
        return node;
    }

    public void put(String key, Object value) {
        Node node = lruMap.get(key);
        if (node == null) {
            if(lruMap.size() >= capacity) {
                String oldKey = removeNode(head);
                lruMap.remove(oldKey);
            }
            node = new Node(key, value);
            addNode(node);
            lruMap.put(key, node);
        } else {
            node.value = value;
            refreshNode(node);
        }
    }

    public void remove(String key) {
        Node node = lruMap.get(key);
        removeNode(node);
        lruMap.remove(key);
    }

    private void refreshNode(Node node) {
        if(tail == node)
            return;
        removeNode(node);
        addNode(node);
    }

    /**
     * 下面代码有漏洞，如果是单节点，也就是head和tail指向同一个节点的时候，需要同时去掉tail和head指向
     *  // 如果是单节点
     *         if (head == node2 && end == node2) {
     *             head = null;
     *             end = null;
     *         } else if (head == node2) {
     *             // 头部节点
     *             head = head.next;
     *             head.pre = null;
     *         } else if (end == node2) {
     *             //尾部节点
     *             end = end.pre;
     *             end.next = null;
     *         } else {
     *             //中间节点
     *             node2.next.pre = node2.pre;
     *             node2.pre.next = node2.next;
     *         }
     *         return node2.key;
     * @param node
     * @return
     */

    private String removeNode(Node node) {
        if (tail == node) {
            tail = node.pre;
        } else if(head == node)
            head = node.next;
        else
            node.pre.next = node.next;
            node.next.pre = node.pre;

        return node.key;
    }

    private void addNode(Node node) {
        if(tail != null) {
            tail.next = node;
            node.pre = tail;
            node.next = null;
        }
        tail = node;
        if (head == null) {
            head = node;
        }
    }


    class Node {
        String key;
        Object value;
        Node pre;
        Node next;
        public Node(String key, Object value) {
            this.key = key;
            this.value = value;
        }

    }


}


class LRUNodeTemp {

    private Integer capacity;
    private HashMap<String, Node> lruMap;
    private Node head;
    private Node tail;

    public void  refresh(Node node) {
        if(tail == node)
            return;
        removeNode(node);
        addNode(node);
    }

    public void del(String key) {
        if (lruMap.get(key) != null) {
            Node node = lruMap.get(key);
            lruMap.remove(key);
            removeNode(node);
        }
    }

    public void add(String key, String value) {
       Node node = lruMap.get(key);
       if (node != null) {
           node.value = value;
           refresh(node);
       } else {
           node = new Node(key, value);
           if (lruMap.size() >= capacity) {
                lruMap.remove(head.key);
                removeNode(head);
           }
           addNode(node);
           lruMap.put(key, node);
       }
    }

    public void addNode(Node node) {
        if (tail != null){
            tail.next = node;
            node.pre = tail;
            node.next = null;
        }
        tail = node;
        if (head == null) {
            head = node;
        }
    }

    public void removeNode(Node node) {
        if (tail ==null) {
            return;
        } else if (tail == node && head == node) {
            tail = null;
            head = null;
        } else if (tail == node) {
            tail.pre.next = null;
            tail = tail.pre;
        } else if (head == node) {
            head.next.pre = null;
            head = head.next;
        } else {
            head.next.pre = head.pre;
            head.pre.next = head.next;
        }
    }


    class Node {
        String key;
        String value;
        Node pre;
        Node next;
        public Node(String key, String value) {
            this.key = key;
            this.value = value;
        }
    }
}

class LRUCacheNode {
    private Integer capacity;
    private HashMap<String, Node> lruMap;
    private Node head;
    private Node tail;


    public void addNode(Node node) {
        if (tail != null) {
            tail.next = node;
            node.pre = tail;
            node.next = null;
        }
        tail = node;
        if (head == null) {
            head = node;
        }
    }

    public void removeNode(Node node) {
        if (tail == node &&  head == node) {
            tail = null;
            head = null;
        } else if (head == node) {
            head  = head.next;
            head.pre = null;
        } else if (tail == node) {
            tail = tail.pre;
            tail.next = null;
        } else  {
            node.pre.next = node.next;
            node.next.pre = node.pre;
        }
    }

    class Node {
        String key;
        String value;
        Node pre;
        Node next;
        public Node(String key, String value) {
            this.key = key;
            this.value = value;
        }
    }

}
